Migo商城2.0 Redis 3.2安装及主从复制详细配置及应用场景 附二
之前存的东西,拿出来改改
一、编译安装
1、下载安装包:http://download.redis.io/releases/redis-3.2.3.tar.gz
目前最新的版本,你也可以打开redis官方的下载页下载合适版本http://redis.io/download
2、开始安装1
2
3
4
5
6
7 wget http://download.redis.io/releases/redis-3.2.3.tar.gz
$ tar xzf redis-3.2.3.tar.gz
$ cd redis-3.2.3
$ make
$ make test #可以先执行make test,查看是否缺少依赖包
$ yum install tcl -y #执行完发现需要安装tcl组件
$ make install
无报错则安装完成,程序文件被安装在了/usr/local/bin
目录下
3、复制配置文件redis.conf
1 | $ mkdir /etc/redis |
4、启动报错处理
我们先不做任何配置启动测试一下
1 | $ /usr/local/bin/redis-server /etc/redis/6379.conf |
redis
默认是前台运行,我们后边再说怎么配置后台运行,这时发现有三个错误,请不要忽略这些信息,接下来我们处理一下这三个错误:
1)第一个错误大概是说somaxconn
的值128
设置过小,从/proc/sys/net/core/somaxconn
这个路径也可大概知道这个值的设置是关于网络连接中某个最大值的限定设置,此值表示网络连接的队列大小,在配置文件redis.conf
中的“tcp-backlog 511
”就配置在高并发环境下的最大队列大小,此值受限于系统的somaxconn
与tcp_max_syn_backlog
这两个值,所以应该把这两个内核参数值调大,具体解决方法如下:
1 | $ vim /etc/sysctl.conf |
2)报错里已经说明了解决方法
1 | 警告:过量使用内存设置为0!在低内存环境下,后台保存可能失败。为了修正这个问题, |
解决方法
1 | $ vim /etc/sysctl |
3)关闭THP透明内存
1 | `Transparent Huge Pages (THP)`告警,这是一个关于透明内存巨页的话题。简单来说内存可管理的最小 |
关于THP的内容就介绍到这里,现在根据警告是做些修改:
1 | $ vim /etc/rc.local |
至此这三个错误就处理好了,再启动就没有错误产生了!
二、配置文件说明
1 | $ vim /etc/redis/6379.conf |
1、后台运行
1 | daemonize yes |
2、bind监听地址
1 | bind 192.168.1.10 |
3、配置密码
1 | # requirepass foobared |
4、日志文件
1 | logfile "/var/log/redis.log" |
5、其他参数
除了上诉几个设置外,还有改端口等一些参数,有需要可以按照配置文件的说明修改。
三、开机启动脚本
redis
安装目录自带了启动脚本,但是不支持restart
,还有在配置了密码验证之后就就不能用了,我贴出一个修改后的启动脚本,可以解决这两个问题。
1 | $ vim /etc/init.d/redis |
修改其中的配置文件路径、你前一步配置的密码等后保存退出。
1 | $ chkconfig redis on |
设置开机启动(根据自己需要来,redis是内存数据库,性能和持久化需要权衡。在配置了主从复制后,
有一种方案是停掉master的持久化功能,这时master服务器上redis需要慎重配置开机启动,后边会详细说明。)
四、Redis持久化
主要是两种方式,可以都用,也可以只开一种,根据自己业务需要配置。
rdb方式rdb
是redis
对数据进行持久化而保存到硬盘的数据文件。
工作原理
1 |
|
默认情况下相关配置如下:
1 | save 900 1 |
其意义为:
1 | 当1个key更新值时每900秒保存一次数据到硬盘 |
换句话说,当你重启服务器时数据是可能会丢失的,如果数据量小的时候,你会丢失5分钟以内的数据;如果数据量大的时候,你会丢失一分钟以内的数据。
所以set name 1
后重启服务器,get name
时的结果会是nil
,如果你想避免这种情况发生,那么可以sav
后重启服务器。
然而大多数情况下我们需要防止的是服务器突发情况下的重启,这时候可能没有机会save,所以还是会造成数据的丢失。所以你可以设置save ""
这样的话会每次写操作到保存到硬盘,但是redis
作为缓存却需要每次到保存到硬盘已丧失了其作为缓存的意义,因此这种方法是不可取的。
还有一种方式,在每次写操作时使用bgsave
命令,可以直接返回操作结果并异步将其保存到硬盘。
rdb
方式的优点是保存的数据存储量小(只有数据)重启速度很快
;缺点是可能会造成数据的丢失
。
aof方式aof
本质是redis
操作(写操作)日志文件。aof默认是未开启的,需要在配置文件中进行设置,在配置文件中将这一行改为appendonly yes
就可以了。
工作原理
1 | AOF :append only file。 |
那么会在什么时候append
到文件末尾呢?有三种方式:
1 | appendfsync always |
aof能够保证数据的安全,但是在重启时比较耗时,而且aof文件的体积比rdb文件大。
使用
在同时开启rdb和aof模式时,会采用aof模式来读取数据。在正常的使用中,如果不是十分在乎短时间内的数据丢失的时候,使用rdb方式会使服务器的效率更高,更节省cpu和硬盘;如果担心数据丢失的话,aof方式无疑会是更好的选择。
五、Redis主从复制
1、概述
Redis
的replication
机制允许slave
从master
那里通过网络传输拷贝到完整的数据备份。具有以下特点:
1.异步复制,从
2.8
版本开始,slave
能不时地从master
那里获取到数据。2.允许单个
master
配置多个slave
3.
slave
允许其它slave
连接到自己。一个slave
除了可以连接master
外,它还可以连接其它的slave
。形成一个图状的架构。4.
master
在进行replication
时是非阻塞的,这意味着在replication
期间,master
依然能够处理客户端的请求。5.
slave
在replication
期间也是非阻塞的,也可以接受来自客户端的请求,但是它用的是之前的旧数据。可以通过配置来决定slave是否在进行replication
时用旧数据响应客户端的请求,如果配置为否,那么slave
将会返回一个错误消息给客户端。不过当新的数据接收完全后,必须将新数据与旧数据替换,即删除旧数据,在替换数据的这个时间窗口内,slave
将会拒绝客户端的请求和连接。6.一般使用
replication
来可以实现扩展性,例如说,可以将多个slave
配置为“只读”,或者是纯粹的数据冗余备份。7.能够通过
replication
来避免master
每次持久化时都将整个数据集持久化到硬盘中。只需把master
配置为不进行持久化操作(把配置文件中持久化相关的配置项注释掉即可),然后连接上一个slave
,这个slave
则被配置持久化选项。不过需要注意的是,在这个方案中,必须确保master
不会自动启动。
2、Master持久化功能关闭时Replication的安全性
当有需要使用到replication
机制时,一般都会强烈建议把master
的持久化开关打开。即使为了避免持久化带来的延迟影响,不把持久化开关打开,那么也应该把master
配置为不会自动启动的。
为了更好地理解当一个不进行持久化的master
如果允许自动启动所带来的危险性。可以看看下面这种失败情形:
假设我们有一个redis
节点A
,设置为master
,并且关闭持久化功能,另外两个节点B
和C
是它的slave
,并从A
复制数据。
如果A
节点崩溃了导致所有的数据都丢失了,它会有重启系统来重启进程。但是由于持久化功能被关闭了,所以即使它重启了,它的数据集是空的。
而B
和C
依然会通过replication
机制从A
复制数据,所以B
和C
会从A
那里复制到一份空的数据集,并用这份空的数据集将自己本身的非空的数据集替换掉。于是就相当于丢失了所有的数据。
即使使用一些HA
工具,比如说sentinel
来监控master-slaves
集群,也会发生上述的情形,因为master
可能崩溃后迅速恢复。速度太快而导致sentinel
无法察觉到一个failure
的发生。
当数据的安全很重要、持久化开关被关闭并且有replication
发生的时候,那么应该**禁止实例的自启动**
。
3、replication工作原理
如果你为master
配置了一个slave
,不管这个slave
是否是第一次连接上Master
,它都会发送一个SYNC
命令给master
请求复制数据。
master
收到SYNC
命令后,会在后台进行数据持久化,持久化期间,master
会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master
会把这份数据集发送给slave
,slave
会把接收到的数据进行持久化,然后再加载到内存中。然后,master
再将之前缓存在内存中的命令发送给slave
。
当master
与slave
之间的连接由于某些原因而断开时,slave
能够自动重连master
,如果master
收到了多个slave
并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave
。
当master
和slave
断开重连后,一般都会对整份数据进行复制。但从redis2.8
版本开始,支持部分复制。
4、数据部分复制
从2.8
版本开始,slave
与master
能够在网络连接断开重连后只进行部分数据复制。
master
会在其内存中创建一个复制流的等待队列,master
和它所有的slave
都维护了复制的数据下标和master
的进程id
,因此,当网络连接断开后,slave
会请求master
继续进行未完成的复制,从所记录的数据下标开始。如果进程id
变化了,或者数据下标不可用,那么将会进行一次全部数据的复制。
5、支持部分数据复制的命令是PSYNC
不需硬盘参与的Replication
一般情况下,一次复制需要将内存的数据写到硬盘中,再将数据从硬盘读进内存,再发送给slave
。
对于速度比较慢的硬盘,这个操作会给master
带来性能上的损失。Redis2.8
版本开始,实验性地加上了无硬盘复制的功能。这个功能能将数据从内存中直接发送到slave
,而不用经过硬盘的存储。
不过这个功能目前处于实验阶段,还未正式发布。
6、主从配置
与replication
相关的配置比较简单,只需要把下面一行加到slave
的配置文件中:
1 | slaveof 192.168.1.1 6379 |
你只需要把ip
地址和端口号改一下。当然,你也可以通过客户端发送SLAVEOF
命令给slave
。
如果master
通过requirepass
配置项设置了密码,slave
每次同步操作都需要验证密码,可以通过在slave
的配置文件中添加以下配置项:
1 | masterauth <password> |
也可以通过客户端在运行时发送以下命令:
1 | config set masterauth <password> |
部分数据复制有一些可调的配置参数,请参考redis.conf
文件。
无硬盘复制功能可以通过repl-diskless-sync
来配置,另外一个配置项repl-diskless-sync-delay
用来配置当收到第一个请求时,等待多个slave
一起来请求之间的间隔时间。
7、只读的slave
从redis2.6
版本开始,slave
支持只读模式,而且是默认
的。可以通过配置项slave-read-only
来进行配置,并且支持客户端使用CONFIG SET
命令来动态修改配置。
只读的slave
会拒绝所有的写请求,只读的slave
并不是为了防范不可信的客户端,毕竟一些管理命令例如DEBUG
和CONFIG
在只读模式下还是可以使用的。如果确实要确保安全性,那么可以在配置文件中将一些命令重新命名。
也许你会感到很奇怪,为什么能够将一个只读模式的slave
恢复为可写的呢,尽管可写,但是只要slave
一同步master
的数据,就会丢失那些写在slave
的数据。不过还是有一些合法的应用场景需要存储瞬时数据会用到这个特性。不过,之后可能会考虑废除掉这个特性。
1 | slave-read-only yes |
8、至少N个slave才允许向master写数据
从redis2.8
版本开始,master
可以被配置为,只有当master
当前有至少N
个slave
连接着的时候才接受写数据的请求。
然而,由于redis
是异步复制的,所以它并不能保证slave
会受到一个写请求,所以总有一个数据丢失的时间窗口存在。
这个机制的工作原理如下所示:
slave每秒发送ping心跳给master,询问当前复制了多少数据。
master会记录下它上次收到某个slave的ping心跳是什么时候。
使用者可以配置一个时间,来指定ping心跳的发送不应超过的一个超时时间
如果master有至少N个slave,并且ping心跳的超时不超过M秒,那么它就会接收写请求。
也许你会认为这情形好似CAP
理论中弱化版的C(consistency)
,因为写请求并不能保证数据的一致性,但这样做,至少数据丢失被限制在了限定的时间内。即M
秒。
如果N
和M
的条件都无法达到,那么master
会回复一个错误信息。写请求也不会被处理。
有两个配置项用来配置上文中提到的N
和M
:
1 | min-slaves-to-write <number of slaves> |
如果需要了解更多,请查阅redis.conf
配置文件。
六、常用命令
1 | redis-cli |
可视化客户端工具
Redis Desktop Manager
(RedisDesktopManager,RDM
)是一个快速、简单、支持跨平台的 Redis
桌面管理工具,基于 Qt 5
开发,支持通过 SSH Tunnel
连接。
1 | 下载地址:https://redisdesktop.com/download |
七、 应用场景
取最新N个数据的操作
比如典型的取你网站的最新文章,通过下面方式,我们可以将最新的5000条评论的ID放在Redis
的List
集合中,并将超出集合部分从数据库获取
使用LPUSH latest.comments<ID>
命令,向list
集合中插入数据
插入完成后再用LTRIM latest.comments 0 5000
命令使其永远只保存最近5000个ID
然后我们在客户端获取某一页评论时可以用下面的逻辑(伪代码)
1
2
3
4
5
6
7FUNCTION get_latest_comments(start,num_items):
id_list = redis.lrange("latest.comments",start,start+num_items-1)
IF id_list.length < num_items
id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...")
END
RETURN id_list
END
如果你还有不同的筛选维度,比如某个分类的最新N条,那么你可以再建一个按此分类的List
,只存ID
的话,Redis
是非常高效的
排行榜应用,取TOP N
操作
这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序,这时候就需要我们的sorted set
出马了,将你要排序的值设置成sorted set
的score
,将具体的数据设置成相应的value
,每次只需要执行一条ZADD
命令即可。
需要精准设定过期时间的应用
比如你可以把上面说到的sorted set
的score
值设置成过期时间的时间戳,那么就可以简单地通过过期时间排序,定时清除过期数据了,不仅是清除Redis中的过期数据,你完全可以把Redis
里这个过期时间当成是对数据库中数据的索引,用Redis
来找出哪些数据需要过期删除,然后再精准地从数据库中删除相应的记录。
计数器应用
Redis
的命令都是原子性的,你可以轻松地利用INCR,DECR
命令来构建计数器系统。
Uniq
操作,获取某段时间所有数据排重值
这个使用Redis
的set数据结构最合适了,只需要不断地将数据往set
中扔就行了,set
意为集合,所以会自动排重。
Pub/Sub
构建实时消息系统
Redis
的Pub/Sub
系统可以构建实时的消息系统,比如很多用Pub/Sub
构建的实时聊天系统的例子。
构建队列系统
使用list
可以构建队列系统,使用sorted set
甚至可以构建有优先级的队列系统。